package updown.service.task;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import updown.dao.DownUpScheduleDao;
import updown.domain.*;
import updown.service.updown.DownUpScheduleService;
import updown.util.DateUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.stream.Collectors;

/**
 * <p>Title: updown.service.task </p>
 * <p>Description:updown: - 定时任务保存 </p>
 *
 * @Author:jiangkaixin
 * @Date:1/5/2022
 * @Version: 1.0
 */
@Slf4j
@Service
public class ScheduleTaskService  {
    @Autowired
    private TaskInfoService taskInfoService;
    @Autowired
    private DownUpScheduleDao downUpScheduleDao;
    @Autowired
    private DownUpScheduleService downUpScheduleService;

    /**
     * 保存任务
     * @param taskWrapper
     */
    public void saveToDB(TaskWrapper taskWrapper) {
        // 1 保存 wrapper
        taskInfoService.add(taskWrapper);
        // 2 保存 schedule
        DownUpSchedule downUpSchedule = taskWrapper.getDownUpSchedule();
        downUpSchedule.setTaskId(taskWrapper.getTaskId());
        downUpScheduleDao.add(downUpSchedule);
    }

    /**
     * 重启之后，把未执行的任务查询来，放入到 schedule Map 中
     */
    public void fillScheduleMapAfterRestart() {
        List<DownUpScheduleWrapperBean> scheduleWrapperBeans = downUpScheduleDao.getAllUnDoneScheduleTask();
        if (scheduleWrapperBeans.isEmpty()){
            log.info("没有未执行的定时任务");
            return;
        }
        List<DownUpSchedule> scheduleList = scheduleWrapperBeans.stream().map(DownUpScheduleWrapperBean::convert).collect(Collectors.toList());
        log.info("重启发现有未执行的 定时任务:{}",scheduleList);

        try {
            for (DownUpSchedule downUpSchedule : scheduleList) {
                TaskWrapper taskWrapper = taskInfoService.getUnDoneScheduleTaskByTaskId(downUpSchedule.getTaskId());
                if (taskWrapper == null){
                    continue;
                }
                Jar jar = Jar.builder()
                        .version(downUpSchedule.getJarVersionInfo())
                        .localFileLocation(downUpSchedule.getLocalFilePath())
                        .originalFileName(downUpSchedule.getOriginalFileName()).build();
                ServiceInfo serviceInfo = ServiceInfo.builder().serviceName(taskWrapper.getServiceName()).build();
                taskWrapper.setServiceInfo(serviceInfo);
                taskWrapper.setJar(jar);
                taskWrapper.setDownUpSchedule(downUpSchedule);
                if (DateUtils.getMinutesBetweenNoError(DateUtils.getCurDateTime(),downUpSchedule.getScheduleTime()) <= 0){
                    log.info("有定时任务，重启时已超时，则不执行定时任务，已完成 + 失败:{}",downUpSchedule);
                    taskWrapper.endFail();
                    downUpSchedule.setDone(Boolean.TRUE);
                    downUpSchedule.setSuccess(Boolean.FALSE);
                    updateScheduleTask(taskWrapper);
                    log.info("定时任务重启，发现已经超过预订的时间，则直接丢弃，保存为任务已完成，并且是失败状态:{}",downUpSchedule);
                    continue;
                }
                // 放入 futureMap，用于取消
                DownUpScheduleService.taskMap.put(taskWrapper.getTaskId(),taskWrapper);
                ScheduledFuture scheduledFuture = downUpScheduleService.scheduleDownUpTask(taskWrapper);
                DownUpScheduleService.futureMap.put(taskWrapper.getTaskId(),scheduledFuture);
            }
        } catch (Exception e) {
            log.info("重新填充任务 error :{}",e);
        }
        log.info("重新填充任务Map 完成");
    }

    /**
     * 执行成功
     * @param taskWrapper
     */
    public void updateScheduleTask(TaskWrapper taskWrapper) {
        taskInfoService.updateTaskWrapper(taskWrapper);
        DownUpSchedule downUpSchedule = taskWrapper.getDownUpSchedule();
        if (taskWrapper.getSuccess()){
            downUpSchedule.setSuccess(Boolean.TRUE);
            downUpSchedule.setDone(Boolean.TRUE);
        }else {
            downUpSchedule.setDone(Boolean.TRUE);
            downUpSchedule.setSuccess(Boolean.FALSE);
        }
        downUpScheduleDao.update(taskWrapper.getDownUpSchedule());
    }

    /**
     * 获取正在 定时器中的任务列表
     * @return
     */
    public List<DownUpSchedule> getSchedulingTasks() {
        List<DownUpSchedule> schedules = new ArrayList<>();
        log.info("getSchedulingTasks() taskMap 中包含的信息是  :{}",DownUpScheduleService.taskMap);
        DownUpScheduleService.taskMap.forEach((taskId,taskWrapper)->{
            schedules.add(taskWrapper.getDownUpSchedule());
        });
        return schedules;
    }

    /**
     * 取消任务
     * @param taskWrapper
     */
    public void cancel(TaskWrapper taskWrapper) {
        // 删除
        DownUpScheduleService.taskMap.remove(taskWrapper.getTaskId());
        DownUpScheduleService.futureMap.remove(taskWrapper.getTaskId());
        // 修改 taskWrapper 的状态
        // 修改 shceduleTask 的状态

        DownUpSchedule downUpSchedule = taskWrapper.getDownUpSchedule();
        downUpSchedule.setDone(Boolean.TRUE);
        downUpSchedule.setEndTime(DateUtils.getCurDateTime());
        downUpScheduleDao.update(downUpSchedule);

        // 修改taskwrapper
        taskWrapper.setSuccess(Boolean.TRUE);
        taskWrapper.setTotalSpend("定时替换已取消");
        taskInfoService.updateTaskWrapper(taskWrapper);
    }
}
